use crate::{
    helpers::{
        count_ttr, create_ttr, redirect_frontends,
        /*count_ttr, create_ttr,*/ link_finder , remove_tracking_parameters,
        wrap_url
    },
};
    use db::{models::{Message, Post, UserPost, UserPostInfo}, Db};
use urlexpand::unshorten;
//  use ActiveValue::NotSet;
use anyhow::{Context, Result};
use log::info;
use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
use tokio_stream::{StreamExt};
// use futures::S
use matrix_sdk::{room::Joined, ruma::events::room::message::OriginalSyncRoomMessageEvent, Client};
use serde::{Deserialize, Serialize};
use url::Url;

/// Add new url to the db and belong it to user
pub async fn add(
    ev: OriginalSyncRoomMessageEvent,
    text: String,
    room: Joined,
    _client: Client,
    db: Db,
) -> Result<()> {
    let urls = link_finder(text.clone());
    if urls.is_empty() {
        info!("no urls in message!")
    }
    let mut urls = tokio_stream::iter(urls);
    // let db = connect_to_db().await?;
        let user_id = ev.sender.as_str();
        println!("{user_id:#?}");
            let user_id = {
                if let Some(user_id) = db.find_user_matrix(&user_id).await.unwrap() {
                    user_id
                } else {
                    db.create_user_matrix(&user_id).await.unwrap()
                }
            };
            
    while let Some(url) =  urls.next().await {
        let db = db.clone();
        let room = room.clone();
        // let text = text.clone();
    tokio::spawn(async move {
        if let Ok(mut url) = Url::parse(&url) {
            remove_tracking_parameters(&mut url);
            let real_url = get_real_url(&url).await;
            let real_url_str = real_url.as_str();

            let post = {
                if let Some(post) = db.find_post(&real_url_str).await.unwrap() {
                    post
                } else {
                    let post = create_post(&real_url).await.unwrap();
                    db.create_post(&post).await.unwrap();
                    post
                }
            };
            let userpost= {
                if let Some(userpost_id) = db.find_user_post(user_id, post.id())
                    .await
                    .unwrap()
                {
                    userpost_id
                } else {
                    let id = db.create_user_post(post.id(), url.as_str(), user_id)
                        .await
                        .unwrap();
                    // UserPostInfo{
                    //     id,
                    //     favorite: false,
                    //     read: false
                    // }
                    id
                }
            };
            // let content = RoomMessageEventContent::text_plain(url.to_string());

            // println!("sending");

            // send our message to the room we found the "!party" command in
            // the last parameter is an optional transaction id which we don't
            // care about.
            // room.send(content, None).await.unwrap();

            // println!("message sent");
            // bot.send_message(telegram_user.id, url.to_string())
            //     .reply_markup(keyboards::standart_keyboard(
            //         &post_id.to_hyphenated().to_string(),
            //         user_post_info.read,
            //         user_post_info.favorite,
            //     ))
            //     .await?;
            // If post does not exist, create it

            // let event_id = ev.event_id.to_string();
            log::info!("Successful saved post");
            // create_message_event(userpost_id, &db, event_id).await.unwrap();
            let mut answer = {
                let url_str = url.as_str();
                if let Some(title) = post.title() {
                    wrap_url(url_str, &title)
                } else {
                    url_str.to_string()
                }
            };
            let ttr = count_ttr(post.word_count());
            if let Some(ttr) = ttr {
                create_ttr(&mut answer, ttr)
            };

            let content = RoomMessageEventContent::text_markdown(answer);

            println!("sending");

            // send our message to the room we found the "!party" command in
            // the last parameter is an optional transaction id which we don't
            // care about.
            let response = room.send(content, None).await.unwrap();
            let event_id = response.event_id.to_string();
            db.create_message_event(userpost.id(), event_id)
                .await
                .unwrap();
            dbg!(response);

            println!("message sent");
        };
    });
        
    }

    //println!("{:#?}", ev);
    //  let urls = link_finder(&text);
    // if urls.is_empty() {
    //     info!("No urls in the message!");
    // }
    // info!("Urls in the message: {:#?}", urls);
    // let db = connect_to_db()
    //     .await
    //     .context("Error while connecting to db:")?;
    // let telegram_user = m.from().context("Error while get telegram user data:")?;
    // let user_id = telegram_user.id;
    // let user_username = telegram_user.username.clone();
    // };
    // for mut url in urls {
    //     remove_tracking_parameters(&mut url);
    //     let mut real_url = real_url(&url).await;
    //     remove_tracking_parameters(&mut real_url);
    //     // If post exists, see if it belongs to the user.
    //     if let Ok(post_id) = post_exists(&real_url, &db).await {
    //         if let Some(user_post_info) =
    //             check_duplicates_in_post_map(user_id, post_id, &db, &url).await?
    //         {
    //             bot.send_message(telegram_user.id, url.to_string())
    //                 .reply_markup(keyboards::standart_keyboard(
    //                     &post_id.to_hyphenated().to_string(),
    //                     user_post_info.read,
    //                     user_post_info.favorite,
    //                 ))
    //                 .await?;
    //         }
    //         // If post does not exist, create it
    //     } else {
    //         let post = create_post(real_url).await?;
    //         save_post_to_db(&post, &db).await?;
    //         append_post_to_user(user_id, post.id(), &db, url.as_str()).await?;
    //         let _post_id = post.id();

    //         log::info!("Successful saved post");
    //         let mut answer = {
    //             let url_str = url.as_str();
    //             if let Some(title) = post.title() {
    //                 wrap_url(url_str, &title)
    //             } else {
    //                 escape(&escape_link_url(url_str))
    //             }
    //         };
    //         let ttr = count_ttr(post.word_count);
    //         if let Some(ttr) = ttr {
    //             create_ttr(&mut answer, ttr)
    //         };
    //         bot.send_message(telegram_user.id, answer)
    //             .reply_markup(keyboards::standart_keyboard(
    //                 &post.id().to_hyphenated().to_string(),
    //                 false,
    //                 false,
    //             ))
    //             //   .parse_mode(ParseMode::MarkdownV2)
    //             .await?;
    //     }
    // }

    Ok(())
}
// use url::Url;
// // Open web page using reqwest and get final url
use reqwest::{Client as ReqwestClient, Proxy};
use std::{ops::Deref, time::Duration};
async fn get_real_url(original_url: &Url) -> Url {
    let proxy = std::env::var("PROXY").unwrap();
    let proxy = reqwest::Proxy::https(proxy).unwrap();
    let timeout = Duration::from_secs(10);
    if let Ok(url) = unshorten(original_url.as_str(), Some(timeout), Some(proxy.clone())).await {
        let url = Url::parse(&url).unwrap();
        info!("{url}");
        url
    } else if let Ok(res) = ReqwestClient::builder()
        .proxy(proxy)
        .build()
        .unwrap()
        .get(original_url.to_owned())
        .timeout(timeout)
        .send()
        .await
    {
        //TODO: work with url
        let real_url = res.url().to_owned();
        info!("{}", real_url);
        real_url
    } else {
        // info!("{:#?}", e);
        original_url.to_owned()
    }
}
use time::OffsetDateTime;
use uuid::Uuid;
fn created() -> OffsetDateTime {
    OffsetDateTime::now_utc()
}
async fn create_post(real_url: &Url) -> Result<Post> {
    let created = created();
    let alternative_url = redirect_frontends(real_url);
    let id = uuid::Uuid::new_v4();
    // let mut title = None;
    // let mut word_count = None;
    let parser_output = parser::parse(real_url).await?;
    // let post = Post::builder()
    //     .id(id)
    //     .created(created)
    //     .real_url(real_url.to_string())
    //     .title(parser_output.title)
    //     .word_count(parser_output.duration.map(|s| s.seconds() as i64))
    //     .alternative_url(alternative_url.map(|s| s.to_string()))
    //     .build();
    let post = Post::new(
        id, parser_output.title, parser_output.duration.map(|s| s.seconds() as i64), real_url.to_string(), alternative_url.map(|s| s.to_string()), created
    );
    Ok(post)
}
